/* Original Author:  Dominick O'Dierno
 * Date: 2007   odiernod@gmail.com     --Originally intended for use with DOMercury:  http://www.odierno.com/domercury
 * Description: The DOMercury Application Context, allows DOMercury to be hidden and activated without closing the program. 
 * This class is also the main controller for user interface functions, triggering the index manager re-index, and other in-use maintenance
 * 
 * --CHANGELOG--
 * 5/13/08 Dominick O'Dierno
 * Added Initialize and Dispose SystemWindowManager calls
 * */

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Drawing;
//using System.Windows;
using System.Windows.Forms;
using ManagedWinapi;
using DOMercury.Managers;
using DOMercury.Forms;
using DOMercury.Interfaces;


namespace DOMercury
{

    class DOMercuryProgramFlowManager : ApplicationContext
    {
        /// <summary>
        /// These functions are here to give some Manager-like functionality to the ProgramManager, namely control of ContextMenu Functions
        /// </summary>
        #region Single Form Instance Code

        private static volatile DOMercuryProgramFlowManager _singleton;
        private static object syncRoot = new Object();

        public static DOMercuryProgramFlowManager Instance
        {
            get
            {
                return _singleton;
            }
            set
            {
                _singleton = value;
            }
        }

        #endregion
        #region Private Members
        private System.Windows.Forms.ContextMenuStrip cmContext;
        private System.Windows.Forms.ToolStripMenuItem setupToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;

        private System.ComponentModel.IContainer components;				
        private System.Windows.Forms.NotifyIcon m_trayIcon;				
        private static ManagedWinapi.Hotkey hk;
        private Timer indexTimer;
        private System.Windows.Forms.Timer updateTimer = null;
        private System.ComponentModel.BackgroundWorker checkupdate;
        #endregion
        private IDOMercuryUserInterface form;
        
        
        public DOMercuryProgramFlowManager()
        {
            //this.WindowStyle = WindowStyle.None;
            //this.AllowsTransparency = true;
            //this.ShowInTaskbar = false;
            //this.Opacity = 0;
            //Display the splash screen during startup
            using (SplashScreen sp = new SplashScreen())
            {
                //create the checkupdate thread
                _singleton = this;
                checkupdate = new System.ComponentModel.BackgroundWorker();
                checkupdate.DoWork += new System.ComponentModel.DoWorkEventHandler(checkupdate_DoWork);
                updateTimer = new Timer();
                updateTimer.Enabled = false;
                updateTimer.Interval = 60000;
                updateTimer.Tick += new EventHandler(updateTimer_Tick);
                ConfigurationManager.LoadCurrentConfiguration();
                
                updateTimer.Enabled = true;
                if (ConfigurationManager.ShowSplashScreen)
                {
                    sp.Show();
                }
                //Load the current configuration
               
                //Initialize Managers
                IconManager.Initialize();
                
                AliasManager.Load();
                PluginManager.LoadPlugins();
                IndexManager.Load();
                SystemWindowManager.Initialize();
                TypeManager.Load();
                InitializeComponents();
                //set the reindex timer
                indexTimer.Start();
                
                //hide the splashscreen
                if (sp.Visible)
                {
                    sp.Hide();
                }
            }
        }

        public IDOMercuryUserInterface MercuryInterface
        {
            get
            {
                return form;
            }
        }

        public System.Windows.Forms.ContextMenuStrip ContextMenu
        {
            get
            {
                return cmContext;
            }
        }

        public void ChangeInterface()
        {
#if DEBUG
            form = new Bezel__.Bezel3();
#else
            foreach (IDOMercuryUserInterfaceProvider i in PluginManager.UserInterfaces)
            {
                if (i.Name == ConfigurationManager.CurrentInterface)
                {
                    form = i.Interface;
                    break;
                }
            }  //TEST
#endif

            
            try
            {
                System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop((System.Windows.Window)form);
            }
            catch { }
            //ShowForm();
        }

        public void ShowOptions()
        {
            setupToolStripMenuItem_Click(new object(), new EventArgs());
        }

        public void Exit()
        {
            exitToolStripMenuItem_Click(new object(), new EventArgs());
        }

        public static ManagedWinapi.Hotkey Hotkey
        {
            get
            {
                return hk;
            }
        }


        void checkupdate_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            CheckVersion();
        }

        //Check for a new version of DOMercury
        private void CheckVersion()
        {
            if (ConfigurationManager.CheckUpdates)
                        {
                //Make sure to only check once a day
                if (ConfigurationManager.LastChecked < DateTime.Now.Subtract(TimeSpan.FromDays(1)))
                {
                    try
                    {
                        DOMercury.CheckVersion.CheckVersion cv = new DOMercury.CheckVersion.CheckVersion();
                        if (cv.CheckNewVersion(System.Windows.Forms.Application.ProductVersion))
                        {
                            
                                System.Windows.MessageBox.Show("There is a new version of DOMercury available.\nYou can download it at http://www.odierno.com/domercury");
                            
                        }

                    }
                    catch { }
                    finally
                    {
                        ConfigurationManager.LastChecked = DateTime.Now;
                    }
                }
            }
        }

        void updateTimer_Tick(object sender, EventArgs e)
        {
            checkupdate.RunWorkerAsync();  
        }

        /// <summary>
        /// Create the NotifyIcon UI, the ContextMenu for the NotifyIcon and an Exit menu item. 
        /// </summary>
        private void InitializeComponents()
        {
            DOMercury.Engine.Interface.EngineCore = new DOMercuryEngineFacade();
            this.components = new System.ComponentModel.Container();
            this.m_trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
            this.cmContext = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.setupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.cmContext.SuspendLayout();

            // 
            // cmContext
            // 
            this.cmContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.setupToolStripMenuItem,
            this.exitToolStripMenuItem});
            this.cmContext.Name = "cmContext";
            this.cmContext.Size = new System.Drawing.Size(117, 48);
            // 
            // setupToolStripMenuItem
            // 
            this.setupToolStripMenuItem.Name = "setupToolStripMenuItem";
            this.setupToolStripMenuItem.Size = new System.Drawing.Size(116, 22);
            this.setupToolStripMenuItem.Text = "&Options";
            this.setupToolStripMenuItem.Click += new System.EventHandler(this.setupToolStripMenuItem_Click);
            // 
            // exitToolStripMenuItem
            // 
            this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
            this.exitToolStripMenuItem.Size = new System.Drawing.Size(116, 22);
            this.exitToolStripMenuItem.Text = "&Exit";
            this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
            // 
            // m_trayIcon.
            // 
            this.m_trayIcon.ContextMenuStrip = cmContext;
            this.m_trayIcon.DoubleClick += new System.EventHandler(this.OnTrayIconDoubleClick);
            this.m_trayIcon.MouseClick += new MouseEventHandler(this.OnTrayIconMouseClick);
            this.m_trayIcon.Icon = System.Drawing.Icon.ExtractAssociatedIcon("tray.ico");//new Icon(typeof(LauncherApplicationContext), "CLOCK05.ICO");
            this.m_trayIcon.Text = "DOMercury";
            this.m_trayIcon.Visible = true;
            //
            // form
            //
            ChangeInterface();

            //
            // HotKey
            //
            ChangeHotkey();
            //
            // IndexTimer
            //
            indexTimer = new Timer();
            indexTimer.Interval = 1000 * 60 * 5;
            indexTimer.Tick += new EventHandler(indexTimer_Tick);
            //System.Windows.Application.Current.Exit +=new ExitEventHandler(OnApplicationExit);
            Application.ApplicationExit += new EventHandler(OnApplicationExit);
            this.cmContext.ResumeLayout(false);

        }

        #region Context Menu
        private void setupToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Show the Setup form
            OptionsForm sf = new OptionsForm();
            sf.Show();

        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Close DOMercury
            // Application.Exit();
        }

        #endregion


        private void ChangeHotkey()
        {
            try
            {
                if (hk != null)
                {
                    hk.Dispose();
                }
                hk = new Hotkey(this.components);
                hk.HotkeyPressed += new EventHandler(OnSystemHotkeyPressed);
                hk.Alt = ConfigurationManager.AltKey;
                hk.Shift = ConfigurationManager.ShiftKey;
                hk.Ctrl = ConfigurationManager.CtrlKey;
                hk.WindowsKey = ConfigurationManager.WindowsKey;
                hk.KeyCode = EnumHelper.StringToEnum<System.Windows.Forms.Keys>(ConfigurationManager.KeyCode);
                
                hk.Enabled = true;
            }
            catch (ManagedWinapi.HotkeyAlreadyInUseException)
            {
                System.Windows.MessageBox.Show("Hotkey Change Failed: Hotkey already in use by another application.\nPlease Change Hotkey in the DOMercury Options Form");
            }
        }

        void OnApplicationExit(object sender, EventArgs e)
        {
            AliasManager.Save();
        }

        private void OnTrayIconDoubleClick(object sender, System.EventArgs e)
        {
            ShowForm();
        }

        private void OnTrayIconMouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                m_trayIcon.ContextMenuStrip.Show();
            }
        }

        private void OnSystemHotkeyPressed(object sender, EventArgs e)
        {            
            ShowForm();
        }

        void indexTimer_Tick(object sender, EventArgs e)
        {
            IndexManager.RebuildIndex();
            System.GC.Collect();
        }

        /// <summary>
        /// SHow the User Interface Form for DOMercury
        /// </summary>
        private void ShowForm()
        {
            ActionManager.ForegroundWindow = ManagedWinapi.Windows.SystemWindow.ForegroundWindow;
            IndexManager.ReEvaluateRealTimePlugins();
            form.ActivateForm();
        }

        /// <summary>
        /// CLose the form
        /// </summary>
        
        protected override void  ExitThreadCore()//protected override void OnClosed(EventArgs e)
        {
            ConfigurationManager.SaveCurrentConfiguration();
            IndexManager.SaveIgnoredFileExtensions();
            IndexManager.SavePriorities();
            SystemWindowManager.Dispose();
            // before we exit, give the main form a chance to clean itself up.
            form.CloseForm();
            
            hk.Enabled = false;
            hk.Dispose();
            //commit suicide
#if DEBUG
#else
            System.Diagnostics.Process.GetCurrentProcess().Kill();

#endif
        base.ExitThreadCore();

 	 //base.OnClosed(e);
        }

    }
    
    class EnumHelper
    {
        public static T StringToEnum<T>(string str)
        {
            if (str.Trim().Length == 0)
            {
                str = "";
            }

            try
            {
                return (T)System.Enum.Parse(typeof(T), str);
            }
            catch
            {
                return default(T);
            }
        }
        public static string EnumToString<T>(T e)
        {
            string str = e.ToString();

            return str;
        }
    } 

    
}
